package com.lin.gameserver.session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 会话管理器，管理所有的游戏会话
 */
public class SessionManager {
    private static final Logger logger = LoggerFactory.getLogger(SessionManager.class);
    
    // 单例实例
    private static final SessionManager INSTANCE = new SessionManager();
    
    // 会话超时时间（毫秒）
    private static final long SESSION_TIMEOUT_MS = 300000; // 5分钟
    
    // 存储会话的Map，key为会话ID，value为会话对象
    private final Map<String, GameSession> sessionMap = new ConcurrentHashMap<>();
    
    // 存储玩家ID到会话ID的映射，用于快速根据玩家ID查找会话
    private final Map<Integer, String> playerSessionMap = new ConcurrentHashMap<>();
    
    // 会话清理调度器
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    
    /**
     * 私有构造方法，确保单例模式
     */
    private SessionManager() {
        // 启动会话清理任务，每分钟执行一次
        scheduler.scheduleAtFixedRate(this::cleanExpiredSessions, 1, 1, TimeUnit.MINUTES);
    }
    
    /**
     * 获取单例实例
     *
     * @return SessionManager实例
     */
    public static SessionManager getInstance() {
        return INSTANCE;
    }
    
    /**
     * 创建新的会话
     *
     * @param webSocketSession WebSocket会话
     * @return 创建的GameSession对象
     */
    public GameSession createSession(Session webSocketSession) {
        GameSession gameSession = new GameSession(webSocketSession);
        sessionMap.put(gameSession.getSessionId(), gameSession);
        logger.info("Session created: {}, total sessions: {}", gameSession.getSessionId(), sessionMap.size());
        return gameSession;
    }
    
    /**
     * 根据会话ID获取会话
     *
     * @param sessionId 会话ID
     * @return GameSession对象，不存在则返回null
     */
    public GameSession getSession(String sessionId) {
        return sessionMap.get(sessionId);
    }
    
    /**
     * 根据玩家ID获取会话
     *
     * @param playerId 玩家ID
     * @return GameSession对象，不存在则返回null
     */
    public GameSession getSessionByPlayerId(int playerId) {
        String sessionId = playerSessionMap.get(playerId);
        if (sessionId != null) {
            return sessionMap.get(sessionId);
        }
        return null;
    }
    
    /**
     * 关闭并移除会话
     *
     * @param sessionId 会话ID
     */
    public void removeSession(String sessionId) {
        GameSession session = sessionMap.remove(sessionId);
        if (session != null) {
            if (session.isAuthenticated()) {
                playerSessionMap.remove(session.getPlayerId());
            }
            session.close();
            logger.info("Session removed: {}, total sessions: {}", sessionId, sessionMap.size());
        }
    }
    
    /**
     * 根据玩家ID关闭并移除会话
     *
     * @param playerId 玩家ID
     */
    public void removeSessionByPlayerId(int playerId) {
        String sessionId = playerSessionMap.remove(playerId);
        if (sessionId != null) {
            removeSession(sessionId);
        }
    }
    
    /**
     * 玩家认证成功后，更新会话状态
     *
     * @param sessionId 会话ID
     * @param playerId 玩家ID
     * @param account 账号
     */
    public void authenticateSession(String sessionId, int playerId, String account) {
        GameSession session = sessionMap.get(sessionId);
        if (session != null) {
            // 如果此玩家已有其他会话，先关闭它
            String existingSessionId = playerSessionMap.get(playerId);
            if (existingSessionId != null && !existingSessionId.equals(sessionId)) {
                removeSession(existingSessionId);
            }
            
            // 设置会话认证信息
            session.setAuthenticated(playerId, account);
            playerSessionMap.put(playerId, sessionId);
            logger.info("Session authenticated: {}, playerId: {}, account: {}", sessionId, playerId, account);
        }
    }
    
    /**
     * 清理过期会话
     */
    private void cleanExpiredSessions() {
        long now = System.currentTimeMillis();
        sessionMap.forEach((sessionId, session) -> {
            if (session.isExpired(SESSION_TIMEOUT_MS)) {
                logger.info("Session expired: {}, last active: {}ms ago", 
                        sessionId, now - session.getLastActiveTime());
                removeSession(sessionId);
            }
        });
    }
    
    /**
     * 获取当前会话数量
     *
     * @return 会话数量
     */
    public int getSessionCount() {
        return sessionMap.size();
    }
    
    /**
     * 获取当前在线玩家数量
     *
     * @return 在线玩家数量
     */
    public int getOnlinePlayerCount() {
        return playerSessionMap.size();
    }
    
    /**
     * 关闭会话管理器
     */
    public void shutdown() {
        scheduler.shutdown();
        sessionMap.forEach((sessionId, session) -> session.close());
        sessionMap.clear();
        playerSessionMap.clear();
        logger.info("SessionManager shutdown");
    }
} 